// 导入第三方npm包(calendar)// const cal = require('calendar').Calendar
const {Calendar} = require('calendar') //对象结构赋值给同名变量
// 导入第三方npm包(lunar-javascript)
const { Solar,HolidayUtil,SolarUtil} = require('lunar-javascript')
const format = {
  // 判断并转换为Date对象
  toDate: function (date) {
    return typeof (date) == "object" ? date : new Date(date)
  },
  date: function (paraDate) {
    let dateObj = this.toDate(paraDate)
    let year = dateObj.getFullYear()
    let month = dateObj.getMonth() + 1
    let day = dateObj.getDate()
    // return [year, formatNumber(month), formatNumber(day)].join('-')
    return [year, month, day].map(formatNumber).join('-')
  },
  yearMonth: function (paraDate) {
    return this.date(paraDate).substr(0, 7)
  },
  time: function (paraTime) {
    let dateObj = this.toDate(paraTime)
    let hour = dateObj.getHours()
    let minute = dateObj.getMinutes()
    let second = dateObj.getSeconds()
    return [hour, minute, second].map(formatNumber).join(':')
  }
}
/* 返回指定年、月（非索引)的公历月历二维数组
 * 参数：isPrevNext：是否返回跨月(上月和下月)数据
 */
const calendar = (y, m, isPrevNext = true) => {
  let calObj = new Calendar()
  let res = []
  if (isPrevNext) {
    // 包含上一个月和下一个月数据的
    res = calObj.monthDates(y, m - 1, date => date.getDate())
  } else {
    //仅指定年有的数据
    res = calObj.monthDays(y, m - 1)
  }
  return res
}
const formatNumber = (n) => {
  n = n.toString()
  return n[1] ? n : `0${n}` //'0' + n
}
/**
 * 将指定公历年、月（非案引)、日转换为农历并返回
 * @param {number} year 公历的年份
 * @param {number} month 公历的月份
 * @param {number} day 公历的月份
 */
function toLunar(year, month, day, isFull = false) {
  // 通过年，月，日获取Solar对象
  let solar = Solar.fromYmd(year, month, day)
  // 转农历
  let lunar = solar.getLunar()
  //法定假日调休 
  let holiday = HolidayUtil.getHoliday(year, month, day)
  // 通过lunar对象获取相应的数据
  let res = {
    year, //year: year
    month,
    day,
    week: solar.getWeek(),
    weekCn: solar.getWeekInChinese(),
    isWork: holiday ? holiday.isWork() : null, //是否调休，调休为true，放假为false
    festivals: solar.getFestivals(),    //公历节日
    otherFestivals: solar.getOtherFestivals(),  //公历纪念日
    lunar: {
      year: lunar.getYear(),
      yearCn: lunar.getYearInChinese(),
      month: lunar.getMonth(),
      monthCn: lunar.getMonthInChinese(),
      day: lunar.getDay(),
      dayCn: lunar.getDayInChinese(),
      shengXiao: {
        year: lunar.getYearShengXiao(),
        month: lunar.getMonthShengXiao(),
        day: lunar.getDayShengXiao()
      },
      ganZhi: {
        year: lunar.getYearInGanZhi(),
        month: lunar.getMonthInGanZhi(),
        day: lunar.getDayInGanZhi()
      },
      jieQi: lunar.getJieQi(),
      festivals: lunar.getFestivals(),    //农历节日
      otherFestivals: lunar.getOtherFestivals(),  //农历纪念日
    }
  }
  let full = null
  if (isFull) {
    full = {
      wuXing: {
        year: lunar.getYearNaYin(),
        month: lunar.getMonthNaYin(),
        day: lunar.getDayNaYin()
      },
      chongSha: {
        chong: lunar.getDayChongDesc(),
        sha: lunar.getDaySha()
      },
      pengZu: {
        gan: lunar.getPengZuGan(),
        zhi: lunar.getPengZuZhi()
      },
      sheng: {
        xi: lunar.getDayPositionXiDesc(),
        fu: lunar.getDayPositionFuDesc(),
        cai: lunar.getDayPositionCaiDesc(),
      },
      yiJi: {
        yi: lunar.getDayYi().join('，'),
        ji: lunar.getDayJi().join('，')
      }
    }
  }
  // 合并多个对象
  Object.assign(res.lunar, full)
  return res
}
/**
 * 返回上一年月
 * @param {int} year 指定的年份
 * @param {int} month 指定的月份
 */
function toPreviousYearMonth(year, month) {
  let result
  if (month == 1) {
    result = {year: year - 1, month: 12}
  } else {
    result = {year, month: month - 1}
  }
  return result
}
/**
 * 返回下一年月
 * @param {int} year 指定的年份
 * @param {int} month 指定的月份
 */
function toNextYearMonth(year, month) {
  return month == 12 ? {year: year + 1, month: 1} : {year, month: month + 1}
}

/**
 * @param {*} year
 * @param {*} month
 * @param {boolean} [isPrevNext=true]
 * @return {*} 
 */
function calendarInLunar(year, month, isPrevNext = true) {
/**
 * 1.通过参数生成公历的月历数据（调用calendar）
 * 2.判断生成的数据是否包合跨月数据
 *  2.1 若不包含：上一月
 *  2.2 下一月单元格用的是0填充
 *  2.3 若包含
 *    2.3.1 判断并获取上一月和下一月的年月
 * 3.遍历公历月历数组，获取指定年、月、日的公、农历数据(调用toLunar方法获取)
 * 4.重新生成含有公历、农历月历二维数组数据。
 */  
let solarCalendar = calendar(year, month, isPrevNext)
//双重循环遍历solarCalendar数组
// 遍历数组的方法:for/for...in/for...of/array.Each()
let result = []
let isPrevMonth = true  //保存是不是上一月的数据
let isNextMonth = false //保存是不是下一月的数据
let currentDays = SolarUtil.getDaysOfMonth(year, month)
let y, m    //生成公农历数据的年月值 

solarCalendar.forEach(week => {
  let weekArray = []
  week.forEach(day => {
    if (isPrevMonth && day !== 1) {
      //是上一月的数据
      let prevYearMonth = toPreviousYearMonth(year, month)
      y = prevYearMonth.year
      m = prevYearMonth.month
    } else if (day === currentDays || isNextMonth) {
      //主要处理下一月的数据(为处理下一月数据做准备)
      isNextMonth = true
      if (day < 7) {
        // 是真正的下一月的数据
        let nextYearMonth = toNextYearMonth(year, month)
        y = nextYearMonth.year
        m = nextYearMonth.month
      }
    } else {
      isPrevMonth = false
      y = year
      m = month
    }
    weekArray.push(day > 0 ? toLunar(y, m, day) : {})
  })
  result.push(weekArray)
})
return result
}

function holidayCountdown(year, month, day) {
  let date = new Date(year, month - 1, day);
  let target = null;
  let result = [];
  let holidys = HolidayUtil.getHolidays(year);
  let privHolidayName = '';
  holidys.forEach(item => {
    target = new Date(item._p.day)
    if (privHolidayName !== item._p.name && item._p.work == false && (target - date) > 0 ) {
      privHolidayName = item._p.name
      result.push({...item._p, days: Math.floor(
        (target - date) / 1000 / 3600 / 24) - 1})
    }
  })
  return result
}

function createSpaces(n) {
  return Array(n + 1).join(' '); // n+1避免IE兼容问题
}
// 暴露方法或变量(导出)
module.exports = {
  format,
  calendar,
  toLunar,
  toNextYearMonth,
  toPreviousYearMonth,
  calendarInLunar,
  holidayCountdown,
  createSpaces
}